package com.hutra.bitmap 
{
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.IBitmapDrawable;
	import flash.display.MovieClip;
	import flash.display.PixelSnapping;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	/**
	 * Data Mix
	 * 'Mi' as micro
	 * 'x' as factors that influence has been incalculable.
	 * 'Mix' as mix together different elements!
	 * 
	 * @source  http://blog.hutrasoft.com/2011/11/movieclip-to-animal-bitmap.html
	 * @svn 	http://hutra.googlecode.com/svn/trunk/
	 * @wiki 	http://wiki.hutrasoft.com/2011/11/datamix.html
	 * @create 	11/05/2011 11:00:02 AM
	 * @author 	hungconcon
	 * @version 1.0.2
	 */
	public class DataMix 
	{
		protected var _w:Number = -1;
		protected var _h:Number = -1;
		protected var _d:Array = null;
		/**
		 * 
		 * @param	a Only Movieclip
		 * @param	b Only width, hight, not-including data
		 */		
		public function DataMix(a:MovieClip,b:Boolean=true) {
			setup(a,b);
		}
		public function get width():Number { return this._w; }
		public function get height():Number {  return this._h; }
		public function get data():Array {  return this._d; }
		/**
		 * @param	a Make sure you seted the movie correctly!
		 * [1] Processing the movieclip, areas
		 * [2] Throw it!
		 */
		private function setup(a:MovieClip,f:Boolean):void {
			//[1]
			var b:Rectangle = getRecBase(a);
			//[1.1]
			if ((b.width <= 1) || (b.height <= 1)) {
				_d = new Array();
				_d.push(new BitmapData(1, 1, true,0x00000000));
				_w = 1;
				_h = 1;
				return;
			}
			//[1.2]
			var c:Array 	= getListBase(a, b);
			var e:Rectangle = getRecActual(c, b);
			var k:Array 	= getListActual(c, e);
			var m:Rectangle = faceBitmap(k);
			//[2]
			_w = m.width;
			_h = m.height;
			if (f) {
				clear(c); // necessary!
				_d = getListActual(k, m);
			}else {
				clear(c); // necessary!
				clear(k); // necessary!
				_d = null;
			}
		}
		/**
		 * Remove excess parts not needed for bitmap
		 * @param	a
		 * @return Rectangle
		 */
		private function faceBitmap(a:Array):Rectangle {
			var c:Number = NaN;
			var d:Number = NaN;
			var e:Number = NaN;
			var f:Number = NaN;
			var g:Number = NaN;
			var h:Number = NaN;
			var k:Number = NaN;
			for (var i:int = 0 ; i < a.length; i++){
				var b:Rectangle = a[i].getColorBoundsRect(0xFFFFFFFF, 0x000000, false);
				if (b.width!=0 && b.height!=0) { //b.x !=0 && b.y!=0 && 
					e = ((k = b.x) < e)?k:(isNaN(e))?k:e;
					f = ((k = b.y) < f)?k:(isNaN(f))?k:f;
					g = ((k = b.width) > g)?k:(isNaN(g))?k:g;
					h = ((k = b.height) > h)?k:(isNaN(h))?k:h;
					
					c = ((k = b.x + b.width) > c)?k:(isNaN(c))?k:c;
					d = ((k = b.y + b.height) > d)?k:(isNaN(d))?k:d;
				}else {
					// I dont like kind of asset!
				}
			}
			var m:Number = c - e;
			var n:Number = d - f;			
			return new Rectangle(e, f, m, n);
		}
		/**
		 * Determine the total area and the initial coordinates of the object.
		 * [1]
		 * Find the smallest value x
		 * Find the smallest value of y
		 * Find the largest value of x
		 * Find the largest value of y
		 * [2]
		 * Find the largest value of width
		 * Find the largest value of hight
		 * [3]
		 * draw an object allows you to define regions of the object
		 * we will remove it when we get the full picture
		 * [4]
		 * Specify the width and height from [1],[2]
		 * @param	a
		 * @return Rectangle
		 */
		private function getRecBase(a:MovieClip):Rectangle {
			var c:int = a.totalFrames;
			var d:Number = NaN;
			var f:Number = NaN;
			var g:Number = NaN;
			var k:Number = NaN;
			var n:Number = NaN;
			var m:Number = NaN;
			var o:Number = NaN;
			//[1]
			for (var i:int = 1; i <= c; i++) {
				a.gotoAndStop(i);
				var b:Rectangle = a.getBounds(a);
				
				g = ((o = b.x) < g)?o:(isNaN(g))?o:g;
				k = ((o = b.y) < k)?o:(isNaN(k))?o:k;
				n = ((o = b.width) > n)?o:(isNaN(n))?o:n;
				m = ((o = b.height) > m)?o:(isNaN(m))?o:m;
				
				d = ((o = b.x + b.width) > d)?o:(isNaN(d))?o:d;
				f = ((o = b.y + b.height) > f)?o:(isNaN(f))?o:f;
			}
			//[2]
			var p:Number = d - g;
			var q:Number = f - k;
			//[3]
			var t:Sprite = new Sprite();
				t.graphics.beginFill(0x000, 0);
				t.graphics.drawRect(g, k, p, q);
				t.graphics.endFill();
				a.addChild(t);
			//[4]	
			var z:Number = dePercent(a.scaleX * 100, 0, p);
			var y:Number = dePercent(a.scaleX * 100, 0, q);
			return new Rectangle(g, k, z, y);
		}
		/**
		 * Retrieving images based on the basic rectangle
		 * @param	a
		 * @param	b
		 * @return
		 */
		private function getListBase(a:MovieClip, b:Rectangle):Array {
			var d:int = a.totalFrames;
			var c:Array = new Array();			
			for (var i:int = 1; i <= d; i++) {
				a.gotoAndStop(i);
				c.push(getBaseBitmapData(a,b,true ));
			}
			return c;
		}
		/**
		 * Find a new Rectangle not including the superfluous
		 * @param	a
		 * @param	b
		 * @return
		 */
		private function getRecActual(a:Array,b:Rectangle):Rectangle {
			var d:Number = NaN;
			var e:Number = NaN;
			var f:Number = NaN;
			var g:BitmapData;
			var h:Rectangle;
			for (var i:int = 0; i <a.length; i++) {
				g = a[i] as BitmapData;
				h = getViboty(g, b);
				d = ((f = h.x) < d)?f:(isNaN(d))?f:d;
				e = ((f = h.y) < e)?f:(isNaN(e))?f:e;
			}
			return new Rectangle(d, e, b.width - d, b.height - e);
		}
		/**
		 * Get visible bounds of transparent 
		 * [1] Frees memory that is used to store the BitmapData object.
		 * @param	a
		 * @param	b
		 * @return Rectangle
		 */
		private function getViboty(a:BitmapData,b:Rectangle): Rectangle {
			var c:BitmapData = new BitmapData(b.width, b.height, true, 0x00000000);
				c.draw(a);
			var d:Rectangle = c.getColorBoundsRect(0xFFFFFFFF, 0x000000, false);
				c.dispose();	//[1]
			  return d;
		}
		/**
		 * [1] Frees memory that is used to store the BitmapData object.
		 * @param	a
		 * @param	b
		 * @return Array
		 */
		private function getListActual(a:Array, b:Rectangle):Array {
			var c:BitmapData;
			var d:Array = new Array();
			for (var i:int = 0; i < a.length; i++) {
				c = a[i] as BitmapData;
				d.push(getActutalBitmapData(c, b));
			}
			clear(a); //[1]
			return d;
		}
		/**
		 * Frees memory!
		 * @param	the arraylist
		 */
		public function clear(a:Array):void {
			if (a == null) return;
			for (var i:int = 0; i < a.length; i++) 
				delete a.splice(i, 1);
			if (a != null) if (a.length > 0) 
				clear(a);
			a = null;
		}
		/**
		 * Move
		 * Center point(0,0)
		 * |----------------|
		 * |	0.0			|
		 * |				|
		 * |		.---------------.
		 * |		|(80,80,100,90)	|
		 * |		|	Object		|
		 * |		|				|
		 * |		.---------------.
		 * |----------------|
		 * 
		 * to
		 * 
		 * .0.0------------.|
		 * |			   ||
		 * |	Object	   ||
		 * |			   ||
		 * .---------------.|
		 * |----------------|
		 * 
		 * @param	a
		 * @param	b
		 * @return
		 */
		private function movePosition(a:Number, b:Number):Number {
			// -25 0 5 =  30 [1]
			// -25 0 -5 = 20 [2]
			//  5  0 25 = 20 [3]
			if (a > 0 && b > 0) return b - a;						//[3]
			if (a < 0 && b < 0) return Math.abs(a) - Math.abs(b); 	//[2]
			if (a < 0 && b > 0) return Math.abs(a) + b; 			//[1]
			return 0;
		}
		/**
		 * [1],[2],[3] Scaled
		 * @param	a
		 * @param	b
		 * @param	c
		 * @return BitmapData
		 */
		private function getBaseBitmapData(a:MovieClip, b:Rectangle, c:Boolean ): BitmapData {
			//[1]
			var f:Rectangle = a.getBounds(a);
			var g:Matrix = new Matrix(1, 0, 0, 1, -f.x, -f.y);
				g.scale(a.scaleX, a.scaleX);
			
			var wi:Number = dePercent(a.scaleX * 100, 0, f.width);		//[2]
			var hi:Number = dePercent(a.scaleX * 100, 0, f.height);	//[3]
			//[4]
			var h:BitmapData = new BitmapData( b.width, b.height, true, 0x00FFFFFF );		
				h.draw(a, g, null, null, null,c);
			//[5]
			var xpo:Number = movePosition(b.x, f.x);
			var ypo:Number = movePosition(b.y, f.y);
			//[6]	
			var k:BitmapData = new BitmapData( b.width, b.height, true, 0x00FFFFFF );
				k.copyPixels(h, new Rectangle(0, 0, b.width, b.height), new Point(xpo, ypo));
			//[7]
			h.dispose();
				
			return k;
		}
		/**
		 * Function on lib: NumberUtilities.as.dePercent()
		 * Percentage change from the current number
		 * @see http://blog.hutrasoft.com/2011/10/16-useful-mathematical-formulas-in.html
		 * @param	percent
		 * @param	start
		 * @param	end
		 * @return number
		 */
		public static function dePercent(p:Number, s:Number = 0, e:Number = 100):Number {
			return (e - ((e - s) - ((p/100) * (e - s))));
		}
		/**
		 * [2] Frees memory that is used to store the BitmapData object.
		 * @param	h
		 * @param	b
		 * @return BitmapData
		 */
		private function getActutalBitmapData(a:BitmapData, b:Rectangle): BitmapData {
			//[1]
			var k:BitmapData = new BitmapData( b.width, b.height, true,0x00FFFFFF);
				k.copyPixels(a, new Rectangle(b.x, b.y, b.width, b.height), new Point(0,0));
			//[2]
				a.dispose(); 
				
			return k;
		}
		
	}
}